package com.base.vistter.iframe.service;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.base.vistter.iframe.bean.SystemContextHolder;
import com.base.vistter.iframe.entity.*;
import com.base.vistter.iframe.exception.IframeException;
import com.base.vistter.iframe.mapper.InverterStationMapper;
import com.base.vistter.iframe.model.EconomyResponse;
import com.base.vistter.iframe.model.StationElectricityOverview;
import com.base.vistter.iframe.model.StationOverview;
import com.base.vistter.iframe.model.StationResponse;
import com.base.vistter.iframe.properties.InverterProperties;
import com.base.vistter.iframe.utils.DateUtils;
import com.base.vistter.iframe.utils.ToolUtils;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.MapUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import java.util.stream.Collectors;

@Slf4j
@Service
@Transactional
public class InverterStationService extends BaseService<InverterStationMapper, InverterStation> {
    @Resource(name = "inverterCollectService")
    private InverterCollectService inverterCollectService;
    @Resource(name = "inverterDevicesPowerDayService")
    private InverterDevicesPowerDayService inverterDevicesPowerService;
    @Resource(name = "sysAreaService")
    private SysAreaService sysAreaService;
    @Resource(name = "inverterDevicesService")
    private InverterDevicesService inverterDevicesService;

    @Resource(name = "inverterDevicesPowerDayService")
    private InverterDevicesPowerDayService inverterDevicesPowerDayService;
    @Resource(name = "inverterDevicesPowerMonthService")
    private InverterDevicesPowerMonthService inverterDevicesPowerMonthService;

    @Resource(name = "inverterDevicesPowerYearService")
    private InverterDevicesPowerYearService inverterDevicesPowerYearService;

    @Resource(name = "inverterDevicesPowerSummaryService")
    private InverterDevicesPowerSummaryService inverterDevicesPowerSummaryService;

    @Resource(name = "inverterProperties")
    private InverterProperties inverterProperties;

    @Transactional(readOnly = true)
    public Page<StationResponse> pageStationApp(Integer pageNo, Integer pageNum, String name, Integer status, String field, String sort) throws IframeException {
        Page<StationResponse> page = Page.of(pageNo, pageNum);
        long total;
        Date startTime = DateUtils.getTodayStartTime();
        Date endTime = DateUtils.getTodayEndTime();
        List<Integer> stationIds = null;
        if (ToolUtils.isAdmin() || ToolUtils.isBusAdmin()) {
            total = this.baseMapper.pageStationAppCount(SystemContextHolder.getSessionContext().getUserId(), name, status, startTime, endTime, null);
            if (total == 0L) {
                return page;
            }
        } else {
            stationIds = this.myStation().stream().map(InverterStation::getId).toList();
            if (stationIds.isEmpty()) {
                return page;
            }
            total = this.baseMapper.pageStationAppCount(SystemContextHolder.getSessionContext().getUserId(), name, status, startTime, endTime, stationIds);
            if (total == 0L) {
                return page;
            }
        }
        page.setTotal(total);
        long start = (page.getCurrent() - 1) * page.getSize();
        List<StationResponse> records;
        if (ToolUtils.isAdmin() || ToolUtils.isBusAdmin()) {
            records = this.baseMapper.pageStationAppList(start, page.getSize(), SystemContextHolder.getSessionContext().getUserId(), name, status, startTime, endTime, null, field, sort);
            page.setRecords(records);
        } else {
            records = this.baseMapper.pageStationAppList(start, page.getSize(), SystemContextHolder.getSessionContext().getUserId(), name, status, startTime, endTime, stationIds, field, sort);
            page.setRecords(records);
        }
        return page;
    }

    @Transactional(readOnly = true)
    public Page<StationResponse> pageCollectStationApp(Integer pageNo, Integer pageNum) throws IframeException {
        Page<StationResponse> page = Page.of(pageNo, pageNum);
        List<Integer> list = inverterCollectService.myCollectIds();
        if (list == null || list.isEmpty()) {
            return page;
        }
        long total;
        Date startTime = DateUtils.getTodayStartTime();
        Date endTime = DateUtils.getTodayEndTime();
        total = this.baseMapper.pageStationAppCount(SystemContextHolder.getSessionContext().getUserId(), null, null, startTime, endTime, list);
        if (total == 0L) {
            return page;
        }
        page.setTotal(total);
        long start = (page.getCurrent() - 1) * page.getSize();
        List<StationResponse> records = this.baseMapper.pageStationAppList(start, page.getSize(), SystemContextHolder.getSessionContext().getUserId(), null, null, startTime, endTime, list, "ic.create_date", "desc");
        page.setRecords(records);
        return page;
    }

    @Transactional(readOnly = true)
    public Page<InverterStation> pageStation(Page<InverterStation> page, String no, String name, Integer inverterStationTypeId, Integer status, Integer collect) throws IframeException {
        LambdaQueryWrapper<InverterStation> lambdaQueryWrapper = new LambdaQueryWrapper<InverterStation>();
        if (StringUtils.isNotEmpty(no)) {
            lambdaQueryWrapper.like(InverterStation::getNo, no);
        }
        if (StringUtils.isNotEmpty(name)) {
            lambdaQueryWrapper.like(InverterStation::getName, name);
        }
        if (inverterStationTypeId != null) {
            lambdaQueryWrapper.eq(InverterStation::getInverterStationTypeId, inverterStationTypeId);
        }
        if (status != null) {
            lambdaQueryWrapper.eq(InverterStation::getStatus, status);
        }
        List<Integer> ids = inverterCollectService.myCollectIds();
        if (collect != null) {
            //未收藏
            if (0 == collect) {
                if (ids != null && !ids.isEmpty()) {
                    lambdaQueryWrapper.notIn(InverterStation::getId, ids);
                }
                //已收藏
            } else {
                if (ids == null || ids.isEmpty()) {
                    return page;
                } else {
                    lambdaQueryWrapper.in(InverterStation::getId, ids);
                }
            }
        }
        if (ToolUtils.isNormalUser()) {
            lambdaQueryWrapper.eq(InverterStation::getSysUserId, SystemContextHolder.getSessionContext().getUserId());
        }
        lambdaQueryWrapper.orderByDesc(InverterStation::getCreateDate);
        page = super.page(page, lambdaQueryWrapper);
        page.getRecords().forEach(item -> {
            if (ids != null && ids.contains(item.getId())) {
                item.setCollect(true);
            } else {
                item.setCollect(false);
            }
            try {
                Map<String, Float> result = inverterDevicesPowerService.getTodayStationElectric(item.getId());
                item.setDayElectric(MapUtils.getFloat(result, "dp", 0f));
            } catch (IframeException e) {
                log.error("获取电站今日电量失败", e);
                throw new RuntimeException(e);
            }
        });
        return page;
    }

    @Transactional(readOnly = true)
    public Long selectCount(Integer inverterStationTypeId) throws IframeException {
        LambdaQueryWrapper<InverterStation> lambdaQueryWrapper = new LambdaQueryWrapper<InverterStation>();
        lambdaQueryWrapper.eq(InverterStation::getInverterStationTypeId, inverterStationTypeId);
        return super.selectCount(lambdaQueryWrapper);
    }

    @Transactional(propagation = Propagation.REQUIRED)
    public boolean save(InverterStation entity) throws IframeException {
        this.serialInverterStation(entity);
        Boolean result = super.save(entity);
        if (!entity.getDevices().isEmpty()) {
            entity.getDevices().forEach(item -> {
                item.setInverterStationId(entity.getId());
            });
        }
        inverterDevicesService.saveBatch(entity.getDevices());
        return result;
    }

    private void serialInverterStation(InverterStation entity) throws IframeException {
        SysArea area = sysAreaService.getSysAreaByCode(entity.getAreaCode());
        if (area != null) {
            entity.setCityName(area.getName());
            SysArea city = sysAreaService.getById(area.getParentId());
            if (city != null) {
                entity.setCityCode(city.getCode());
                entity.setCityName(city.getName());
                SysArea province = sysAreaService.getById(city.getParentId());
                if (province != null) {
                    entity.setProvinceCode(province.getCode());
                    entity.setProvinceName(province.getName());
                }
            }

        }
    }

    @Transactional(propagation = Propagation.REQUIRED)
    public boolean updateById(InverterStation entity) throws IframeException {
        InverterStation inverterStation = super.getById(entity.getId());
        if (!Objects.equals(inverterStation.getAreaCode(), entity.getAreaCode())) {
            this.serialInverterStation(entity);
        }
        return super.updateById(entity);
    }

    @Transactional(readOnly = true)
    public List<Map<String, Object>> countStatus() throws IframeException {
        QueryWrapper<InverterStation> queryWrapper = Wrappers.query();
        queryWrapper.select("status", "count(*) as counting");
        if (ToolUtils.isNormalUser()) {
            queryWrapper.eq("sys_user_id", SystemContextHolder.getSessionContext().getUserId()).groupBy("status");
        }
        queryWrapper.groupBy("status");
        return super.selectMaps(queryWrapper);
    }

    @Transactional(readOnly = true)
    public StationElectricityOverview getStationElectricityOverview(Integer stationId) throws IframeException {
        //单个电站
        if (stationId != null) {
            Map<String, Float> result = inverterDevicesPowerService.getTodayStationElectric(stationId);
            Float dp = MapUtils.getFloat(result, "dp", 0f); // 今日发电量
            Float p = MapUtils.getFloat(result, "p", 0f); //功率

            InverterStation inverterStation = super.getById(stationId);
            Float totalElectricity = inverterStation.getTotalElectric() + dp; //总发电量
            Float totalMonthElectricity = inverterStation.getMonthElectric() + dp; //当月发电量
            Float totalYearElectricity = inverterStation.getYearElectric() + dp; //当年发电量
            Float totalPower = inverterStation.getPower() + p; //当前总功率
            return new StationElectricityOverview(totalElectricity, inverterStation.getCapacity(), dp, totalMonthElectricity, totalYearElectricity, totalPower, inverterStation.getElectricCharge());
            //所有电站
        } else {
            Map<String, Float> result = inverterDevicesPowerService.getTodayElectric();
            Float dp = MapUtils.getFloat(result, "dp", 0f); // 今日发电量
            Float p = MapUtils.getFloat(result, "p", 0f); //功率

            Map<String, Float> station = this.baseMapper.getElectric(); //电站
            Float totalElectricity = MapUtils.getFloat(station, "te", 0f) + dp; //总发电量
            Float totalCapacity = MapUtils.getFloat(station, "cs", 0f);  //总容量
            Float totalMonthElectricity = MapUtils.getFloat(station, "me", 0f) + dp; //当月发电量
            Float totalYearElectricity = MapUtils.getFloat(station, "ye", 0f) + dp; //当年发电量

            Float totalPower = MapUtils.getFloat(station, "ps", 0f) + p; //当前总功率
            return new StationElectricityOverview(totalElectricity, totalCapacity, dp, totalMonthElectricity, totalYearElectricity, totalPower);
        }
    }

    @Transactional(readOnly = true)
    public StationOverview getStationOverview() throws IframeException {
        //如果是超级管理员
        LambdaQueryWrapper<InverterStation> lambdaQueryWrapper = Wrappers.lambdaQuery();
        List<Map<String, Object>> list = this.countStatus();
        Integer total = super.selectCount(lambdaQueryWrapper).intValue();
        Map<Integer, Integer> result = list.stream().collect(Collectors.toMap(item -> MapUtils.getInteger(item, "status"), item -> MapUtils.getInteger(item, "counting")));
        //正常
        Integer normal = MapUtils.getInteger(result, 0, 0);
        //待机
        Integer standby = MapUtils.getInteger(result, 1, 0);
        //告警
        Integer warning = MapUtils.getInteger(result, 2, 0);
        //故障
        Integer error = MapUtils.getInteger(result, 3, 0);
        //离线
        Integer offline = MapUtils.getInteger(result, 4, 0);
        //建设中
        Integer construction = MapUtils.getInteger(result, 5, 0);
        return new StationOverview(total, normal, standby, warning, error, offline, construction);
    }

    @Transactional(readOnly = true)
    public List<InverterDevicesPowerDay> statisticsDay(Date time, Integer stationId) throws IframeException {
        return inverterDevicesPowerDayService.statisticsDay(time, stationId);
    }

    @Transactional(readOnly = true)
    public List<InverterDevicesPowerMonth> statisticsMonth(Date time, Integer stationId) throws IframeException {
        List<InverterDevicesPowerMonth> list = inverterDevicesPowerMonthService.statisticsMonth(stationId, time);
        if (DateUtils.isCurrentMonth(time)) {
            Map<String, Float> map = inverterDevicesPowerDayService.getTodayStationElectric(stationId);
            if (map != null && !map.isEmpty()) {
                InverterDevicesPowerMonth today = new InverterDevicesPowerMonth();
                today.setDP(MapUtils.getFloat(map, "dp", 0f));
                today.setReportTime(new Date());
                list.add(today);
            }
        }
        return list;
    }

    @Transactional(readOnly = true)
    public List<InverterDevicesPowerYear> statisticsYear(Integer time, Integer stationId) throws IframeException {
        return inverterDevicesPowerYearService.statisticsYear(stationId, time);
    }

    @Transactional(readOnly = true)
    public List<InverterDevicesPowerSummary> statisticsSummary(Integer stationId) throws IframeException {
        return inverterDevicesPowerSummaryService.statisticsSummary(stationId);
    }

    @Transactional(readOnly = true)
    public List<InverterStation> myStation() throws IframeException {
        LambdaQueryWrapper<InverterStation> lambdaQueryWrapper = Wrappers.lambdaQuery();
        if (ToolUtils.isNormalUser()) {
            lambdaQueryWrapper.eq(InverterStation::getSysUserId, SystemContextHolder.getSessionContext().getUserId());
        }
        lambdaQueryWrapper.orderByDesc(InverterStation::getCreateDate);
        return super.selectList(lambdaQueryWrapper);
    }

    @Transactional(readOnly = true)
    public EconomyResponse economy(Integer stationId) throws IframeException {
        Map<String, Float> result = inverterDevicesPowerService.getTodayStationElectric(stationId);
        Float dp = MapUtils.getFloat(result, "dp", 0f); // 今日发电量
        InverterStation inverterStation = super.getById(stationId);
        return new EconomyResponse(inverterStation.getTotalElectric() + dp, inverterStation.getElectricCharge(), inverterProperties);
    }

}
